home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / planner / plan / setrefs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  22.8 KB  |  858 lines

  1. /*     
  2.  *      FILE
  3.  *         setrefs
  4.  *     
  5.  *      DESCRIPTION
  6.  *         Routines to change varno/attno entries to contain references
  7.  *     
  8.  */
  9.  
  10. /* RcsId ("$Header: /private/postgres/src/planner/plan/RCS/setrefs.c,v 1.27 1992/07/09 03:56:35 hong Exp $"); */
  11.  
  12. /*     
  13.  *      EXPORTS
  14.  *             new-level-tlist
  15.  *             new-level-qual
  16.  *             new-result-tlist
  17.  *             new-result-qual
  18.  *             set-tlist-references
  19.  *             index-outerjoin-references
  20.  *             join-references
  21.  *             tlist-temp-references
  22.  */
  23. #include "tmp/c.h"
  24.  
  25. #include "nodes/pg_lisp.h"
  26. #include "nodes/plannodes.h"
  27. #include "nodes/plannodes.a.h"
  28. #include "nodes/primnodes.h"
  29. #include "nodes/primnodes.a.h"
  30. #include "nodes/relation.h"
  31. #include "nodes/relation.a.h"
  32.  
  33. #include "parser/parse.h"
  34.  
  35. #include "utils/log.h"
  36. #include "tmp/nodeFuncs.h"
  37.  
  38. #include "planner/internal.h"
  39. #include "planner/clause.h"
  40. #include "planner/clauseinfo.h"
  41. #include "planner/clauses.h"
  42. #include "planner/keys.h"
  43. #include "planner/setrefs.h"
  44. #include "planner/tlist.h"
  45. #include "planner/var.h"
  46.  
  47. /*     
  48.  *         NESTING LEVEL REFERENCES
  49.  *     
  50.  */
  51.  
  52. /*     
  53.  *         RESULT REFERENCES
  54.  *     
  55.  */
  56.  
  57. /*    
  58.  *        new-result-tlist
  59.  *    
  60.  *        Creates the target list for a result node by copying a tlist but
  61.  *        assigning reference values for the varno entry.  The reference pair 
  62.  *        corresponds to the nesting level where the attribute can be found and 
  63.  *        the result domain number within the tuple at that nesting level.
  64.  *    
  65.  *        'tlist' is the the target list to be copied
  66.  *        'ltlist' is the target list from level 'levelnum'
  67.  *        'rtlist' is the target list from level 'levelnum+1'
  68.  *        'levelnum' is the current nesting level
  69.  *        'sorted' is t if the desired user result has been sorted in
  70.  *            some internal node
  71.  *    
  72.  *        Returns the new target list.
  73.  *    
  74.  */
  75.  
  76. /*  .. query_planner     */
  77.  
  78. LispValue
  79. new_result_tlist (tlist,ltlist,rtlist,levelnum,sorted)
  80.      LispValue tlist,ltlist,rtlist;
  81.      int levelnum;
  82.      bool sorted;
  83. {
  84.     LispValue t_list = LispNil;
  85.     
  86.     if ( consp (tlist) ) {
  87.       if ( consp (rtlist) ) {
  88.           LispValue xtl = LispNil;
  89.           LispValue temp = LispNil;
  90.           TLE entry;
  91.           
  92.           foreach(xtl,tlist) {
  93.           entry = CAR(xtl);
  94.           if ( sorted) {
  95.               set_reskey ((Resdom)tl_resdom(entry),0);
  96.               set_reskeyop ((Resdom)tl_resdom(entry),0);
  97.           }
  98.           temp = lispCons(tl_resdom (entry),
  99.                   lispCons 
  100.                   ((LispValue)replace_clause_resultvar_refs 
  101.                    ((Expr)get_expr(entry),
  102.                     ltlist,
  103.                     rtlist,
  104.                     levelnum),
  105.                    LispNil));
  106.           t_list = nappend1(t_list,temp);
  107.            }
  108.           return(t_list);
  109.       }
  110.       else
  111.         return (tlist);
  112.      }
  113.      else
  114.        return(LispNil);
  115.  
  116. }  /* function end  */
  117.  
  118. /*    
  119.  *        new-result-qual
  120.  *    
  121.  *        Modifies a list of relation level clauses by assigning reference
  122.  *        values for varnos within vars appearing in the clauses.
  123.  *    
  124.  *        'relquals' is the list of relation level clauses    
  125.  *        'ltlist' is the target list from level 'levelnum'
  126.  *        'rtlist' is the target list from level 'levelnum+1'
  127.  *        'levelnum' is the current nesting level
  128.  *    
  129.  *        Returns a new qualification.
  130.  *    
  131.  */
  132.  
  133. /*  .. query_planner        */
  134.  
  135. LispValue
  136. new_result_qual (clauses,ltlist,rtlist,levelnum)
  137.      LispValue clauses,ltlist,rtlist;
  138.      int levelnum ;
  139. {
  140.      return (replace_subclause_resultvar_refs (clauses,
  141.                            ltlist,
  142.                            rtlist,
  143.                            levelnum));
  144. } /* function end  */
  145.  
  146. /*    
  147.  *        replace-clause-resultvar-refs
  148.  *        replace-subclause-resultvar-refs
  149.  *        replace-resultvar-refs
  150.  *    
  151.  *        Creates a new expression corresponding to a target list entry or
  152.  *        qualification in a result node by replacing the varno value in all
  153.  *        vars with a reference pair.  The reference pair is assigned by finding
  154.  *        a matching var in a previous target list.  If the var already is a
  155.  *        reference to a previous nesting, the var is just returned.
  156.  *    
  157.  *        'expr' is the target list entry or qualification
  158.  *        'ltlist' is the target list from level 'levelnum'
  159.  *        'rtlist' is the target list from level 'levelnum+1'
  160.  *        'levelnum' is the current nesting level
  161.  *    
  162.  *        Returns the new target list entry.
  163.  *    
  164.  */
  165.  
  166. /*  .. new-result-tlist, replace-clause-resultvar-refs
  167.  *  .. replace-subclause-resultvar-refs
  168.  */
  169.  
  170. Expr
  171. replace_clause_resultvar_refs (clause,ltlist,rtlist,levelnum)
  172.      Expr clause;
  173.      List ltlist,rtlist;
  174.      int levelnum ;
  175. {
  176.     if(IsA (clause,Var) && (get_varattno ((Var)clause) == 0))
  177.       return(clause);
  178.     else if (IsA (clause,Var)) 
  179.       return ((Expr)replace_resultvar_refs((Var)clause,
  180.                     ltlist,
  181.                     rtlist,
  182.                     levelnum));
  183.     else if (single_node ((Node)clause)) 
  184.       return (clause);
  185.     else if (or_clause ((LispValue)clause)) 
  186.       return ((Expr)make_orclause (replace_subclause_resultvar_refs 
  187.                    (get_orclauseargs ((LispValue)clause),
  188.                     ltlist,
  189.                     rtlist,
  190.                     levelnum)));
  191.     else if (IsA(clause,ArrayRef)) {
  192.       Expr temp;
  193.       temp = replace_clause_resultvar_refs(get_refindexpr((ArrayRef)clause),
  194.                           ltlist,
  195.                           rtlist,
  196.                           levelnum);
  197.       set_refindexpr((ArrayRef)clause,(LispValue)temp);
  198.       temp = replace_clause_resultvar_refs(get_refexpr((ArrayRef)clause),
  199.                           ltlist,
  200.                           rtlist,
  201.                           levelnum);
  202.       set_refexpr((ArrayRef)clause,(LispValue)temp);
  203.       return(clause);
  204.     }
  205.     else if (is_funcclause ((LispValue)clause)) 
  206.       return ((Expr)make_funcclause (get_function ((LispValue)clause),
  207.                     replace_subclause_resultvar_refs 
  208.                     (get_funcargs ((LispValue)clause),
  209.                      ltlist,
  210.                      rtlist,
  211.                      levelnum)));
  212.     else if (not_clause ((LispValue)clause))
  213.       return((Expr)make_notclause((List)replace_clause_resultvar_refs
  214.                    ((Expr)get_notclausearg ((LispValue)clause),
  215.                       ltlist,
  216.                       rtlist,
  217.                       levelnum)));
  218.      else /*   operator clause */
  219.       return((Expr)make_opclause(replace_opid((Oper)get_op((LispValue)clause)),
  220.                     (Var)replace_clause_resultvar_refs 
  221.                     ((Expr)get_leftop((LispValue)clause),
  222.                      ltlist,
  223.                      rtlist,
  224.                      levelnum),
  225.                     (Var)replace_clause_resultvar_refs 
  226.                     ((Expr)get_rightop((LispValue)clause),
  227.                      ltlist,
  228.                      rtlist,
  229.                      levelnum)));
  230. }  /* function end  */
  231.  
  232. /*  .. new-result-qual, replace-clause-resultvar-refs     */
  233.  
  234. LispValue
  235. replace_subclause_resultvar_refs (clauses,ltlist,rtlist,levelnum)
  236.      LispValue clauses,ltlist,rtlist;
  237.      int levelnum ;
  238. {
  239.      LispValue t_list = LispNil;
  240.      LispValue clause = LispNil;
  241.      LispValue temp = LispNil;
  242.  
  243.      foreach(clause,clauses) {
  244.      temp = (LispValue)replace_clause_resultvar_refs ((Expr)CAR(clause),
  245.                               ltlist,
  246.                               rtlist,
  247.                               levelnum);
  248.      t_list = nappend1(t_list,temp);
  249.      }
  250.      return(t_list);
  251. }  /* function end  */
  252.  
  253. /*  .. replace-clause-resultvar-refs       */
  254.  
  255. Var
  256. replace_resultvar_refs (var,ltlist,rtlist,levelnum)
  257.      Var var;
  258.      List ltlist,rtlist;
  259.      int levelnum ;
  260. {
  261.      LispValue varno = LispNil;
  262.      
  263.      if (levelnum == numlevels (var)) 
  264.       varno = lispCons (lispInteger(levelnum - 1),
  265.                 lispCons((LispValue)get_resno ((Resdom)tl_resdom 
  266.                           (match_varid (var, ltlist))),
  267.                      LispNil));
  268.      else
  269.        varno = lispCons (lispInteger(levelnum),
  270.              lispCons ((LispValue)get_resno ((Resdom)tl_resdom 
  271.                       (match_varid (var, rtlist))),
  272.                    LispNil));
  273.      
  274.      return (MakeVar ((Index)varno,
  275.               0,
  276.               get_vartype (var),
  277.               get_varid (var), (Pointer)NULL));
  278.      
  279.  } /* function end */
  280.  
  281. /*     
  282.  *         SUBPLAN REFERENCES
  283.  *     
  284.  */
  285.  
  286. /*    
  287.  *        set-tlist-references
  288.  *    
  289.  *        Modifies the target list of nodes in a plan to reference target lists
  290.  *        at lower levels.
  291.  *    
  292.  *        'plan' is the plan whose target list and children's target lists will
  293.  *            be modified
  294.  *    
  295.  *        Returns nothing of interest, but modifies internal fields of nodes.
  296.  *    
  297.  */
  298.  
  299. /* query_planner, set-join-tlist-references, set-temp-tlist-references     */
  300.  
  301. void
  302. set_tlist_references (plan)
  303.      Plan plan ;
  304. {
  305.     if(null (plan)) 
  306.       LispNil;
  307.     else 
  308.       if (IsA (plan,Join)) 
  309.     set_join_tlist_references ((Join)plan);
  310.       else 
  311.     if (IsA(plan,SeqScan) &&
  312.         get_lefttree (plan) && 
  313.         IsA (get_lefttree(plan),Temp))
  314.       set_tempscan_tlist_references((SeqScan)plan);
  315.     else 
  316.       if (IsA (plan,Sort))
  317.         set_temp_tlist_references ((Temp)plan);
  318.       else if (IsA(plan,Result))
  319.         set_result_tlist_references((Result)plan);
  320.         else if (IsA(plan,Hash))
  321.         set_tlist_references((Plan)get_lefttree(plan));
  322.         else if (IsA(plan,Choose)) {
  323.         LispValue x;
  324.         foreach (x, get_chooseplanlist((Choose)plan)) {
  325.             set_tlist_references((Plan)CAR(x));
  326.           }
  327.           }
  328.  
  329. }   /* function end  */
  330.  
  331. /*    
  332.  *        set-join-tlist-references
  333.  *    
  334.  *        Modifies the target list of a join node by setting the varnos and
  335.  *        varattnos to reference the target list of the outer and inner join
  336.  *        relations.
  337.  *    
  338.  *        Creates a target list for a join node to contain references by setting 
  339.  *        varno values to OUTER or INNER and setting attno values to the 
  340.  *        result domain number of either the corresponding outer or inner join 
  341.  *        tuple.
  342.  *    
  343.  *        'join' is a join plan node
  344.  *    
  345.  *       Returns nothing of interest, but modifies internal fields of nodes.
  346.  *    
  347.  */
  348.  
  349. /*  .. set-tlist-references       */
  350.  
  351. void 
  352. set_join_tlist_references (join)
  353.      Join join ;
  354. {
  355.     Plan     outer = (Plan)get_lefttree ((Plan)join);
  356.     Plan    inner = (Plan)get_righttree ((Plan)join);
  357.     List     new_join_targetlist = LispNil;
  358.     TLE        temp = (TLE)NULL;
  359.     LispValue      entry = LispNil;
  360.     List    inner_tlist = NULL;
  361.     List    outer_tlist = NULL;
  362.     TLE    xtl =     (TLE)NULL;
  363.     List    qptlist = get_qptargetlist((Plan)join);
  364.  
  365.      foreach(entry,qptlist) {
  366.      xtl = (TLE)CAR(entry);
  367.      inner_tlist = ( null(inner) ? LispNil : get_qptargetlist(inner));
  368.      outer_tlist = ( null(outer) ? LispNil : get_qptargetlist(outer));
  369.  
  370.      temp = MakeTLE(tl_resdom (xtl),
  371.             replace_clause_joinvar_refs((LispValue)get_expr(xtl),
  372.                              outer_tlist,
  373.                              inner_tlist)
  374.             );
  375.      new_join_targetlist = nappend1(new_join_targetlist,temp);
  376.      }
  377.     
  378.     set_qptargetlist ((Plan)join,new_join_targetlist);
  379.     if ( ! null (outer))
  380.       set_tlist_references (outer);
  381.     if ( ! null (inner))
  382.       set_tlist_references (inner);
  383.     
  384. } /* function end  */
  385.  
  386. /*    
  387.  *        set-tempscan-tlist-references
  388.  *    
  389.  *        Modifies the target list of a node that scans a temp relation (i.e., a
  390.  *        sort or hash node) so that the varnos refer to the child temporary.
  391.  *    
  392.  *        'tempscan' is a seqscan node
  393.  *    
  394.  *        Returns nothing of interest, but modifies internal fields of nodes.
  395.  *    
  396.  */
  397.  
  398. /*  .. set-tlist-references     */
  399.  
  400. void
  401. set_tempscan_tlist_references (tempscan)
  402.      SeqScan tempscan ;
  403. {
  404.  
  405.      Temp temp = (Temp)get_lefttree((Plan)tempscan);
  406.      set_qptargetlist ((Plan)tempscan,
  407.                tlist_temp_references(get_tempid(temp),
  408.                          get_qptargetlist((Plan)tempscan)));
  409.      set_temp_tlist_references (temp);
  410.  
  411. }  /* function end  */
  412.  
  413. /*    
  414.  *        set-temp-tlist-references
  415.  *    
  416.  *        The temp's vars are made consistent with (actually, identical to) the
  417.  *        modified version of the target list of the node from which temp node
  418.  *        receives its tuples.
  419.  *    
  420.  *        'temp' is a temp (e.g., sort, hash) plan node
  421.  *    
  422.  *        Returns nothing of interest, but modifies internal fields of nodes.
  423.  *    
  424.  */
  425.  
  426. /*  .. set-tempscan-tlist-references, set-tlist-references      */
  427.  
  428. void 
  429. set_temp_tlist_references (temp)
  430.      Temp temp ;
  431. {
  432.      Plan source = (Plan)get_lefttree ((Plan)temp);
  433.  
  434.      if (!null(source)) {
  435.      set_tlist_references (source);
  436.      set_qptargetlist ((Plan)temp,
  437.                copy_vars (get_qptargetlist ((Plan)temp),
  438.                       get_qptargetlist (source)));
  439.      }
  440.      else
  441.        printf (" WARN: calling set_temp_tlist_references with empty lefttree\n");
  442.  }  /* function end  */
  443.  
  444. /*    
  445.  *        join-references
  446.  *    
  447.  *        Creates a new set of join clauses by replacing the varno/varattno
  448.  *        values of variables in the clauses to reference target list values
  449.  *        from the outer and inner join relation target lists.
  450.  *    
  451.  *        'clauses' is the list of join clauses
  452.  *        'outer-tlist' is the target list of the outer join relation
  453.  *        'inner-tlist' is the target list of the inner join relation
  454.  *    
  455.  *        Returns the new join clauses.
  456.  *    
  457.  */
  458.  
  459. /* create_hashjoin_node, create_mergejoin_node, create_nestloop_node     */
  460.  
  461. LispValue
  462. join_references (clauses,outer_tlist,inner_tlist)
  463.      LispValue clauses,outer_tlist,inner_tlist ;
  464. {
  465.      return (replace_subclause_joinvar_refs (clauses,
  466.                          outer_tlist,
  467.                          inner_tlist));
  468. }  /* function end  */
  469.  
  470. /*    
  471.  *        index-outerjoin-references
  472.  *    
  473.  *        Given a list of join clauses, replace the operand corresponding to the
  474.  *        outer relation in the join with references to the corresponding target
  475.  *        list element in 'outer-tlist' (the outer is rather obscurely
  476.  *        identified as the side that doesn't contain a var whose varno equals
  477.  *        'inner-relid').
  478.  *    
  479.  *        As a side effect, the operator is replaced by the regproc id.
  480.  *    
  481.  *        'inner-indxqual' is the list of join clauses (so-called because they
  482.  *        are used as qualifications for the inner (inbex) scan of a nestloop)
  483.  *    
  484.  *        Returns the new list of clauses.
  485.  *    
  486.  */
  487.  
  488. /*  .. create_nestloop_node     */
  489.  
  490. LispValue
  491. index_outerjoin_references (inner_indxqual,outer_tlist,inner_relid)
  492.      LispValue inner_indxqual,outer_tlist;
  493.      Index inner_relid ;
  494. {
  495.     LispValue t_list = LispNil;
  496.     LispValue temp = LispNil;
  497.     LispValue t_clause = LispNil;
  498.     LispValue clause = LispNil;
  499.  
  500.     foreach (t_clause,inner_indxqual) {
  501.     clause = CAR(t_clause);
  502.     /*
  503.      * if inner scan on the right.
  504.      */
  505.     if(OperandIsInner((LispValue)get_rightop(clause), inner_relid)) {
  506.         temp = make_opclause(replace_opid((Oper)get_op (clause)),
  507.                  (Var)replace_clause_joinvar_refs 
  508.                   ((LispValue)get_leftop (clause),
  509.                    outer_tlist,
  510.                    LispNil),
  511.                   get_rightop (clause));
  512.         t_list = nappend1(t_list,temp);
  513.     } 
  514.     else {   /*   inner scan on left */
  515.         temp = make_opclause(replace_opid((Oper)get_op(clause)),
  516.                 get_leftop (clause),
  517.                 (Var)replace_clause_joinvar_refs(
  518.                         (LispValue)get_rightop(clause),
  519.                         outer_tlist,
  520.                         LispNil));
  521.         t_list = nappend1(t_list,temp);
  522.     } 
  523.     
  524.      }
  525.     return(t_list);
  526.      
  527. }  /* function end  */
  528.  
  529. /*    
  530.  *        replace-clause-joinvar-refs
  531.  *        replace-subclause-joinvar-refs
  532.  *        replace-joinvar-refs
  533.  *    
  534.  *        Replaces all variables within a join clause with a new var node
  535.  *        whose varno/varattno fields contain a reference to a target list
  536.  *        element from either the outer or inner join relation.
  537.  *    
  538.  *        'clause' is the join clause
  539.  *        'outer-tlist' is the target list of the outer join relation
  540.  *        'inner-tlist' is the target list of the inner join relation
  541.  *    
  542.  *        Returns the new join clause.
  543.  *    
  544.  */
  545.  
  546. /*  .. index-outerjoin-references, replace-clause-joinvar-refs
  547.  *  .. replace-subclause-joinvar-refs, set-join-tlist-references
  548.  */
  549. LispValue
  550. replace_clause_joinvar_refs (clause,outer_tlist,inner_tlist)
  551.      LispValue clause,outer_tlist,inner_tlist ;
  552. {
  553.     LispValue temp = LispNil;
  554.     if(IsA (clause,Var)) {
  555.     if(temp = (LispValue)
  556.        replace_joinvar_refs((Var)clause,outer_tlist,inner_tlist))
  557.        return(temp);
  558.     else
  559.       if (clause != LispNil)
  560.         return(clause);
  561.       else
  562.         return(LispNil);
  563.     }
  564.     else if (single_node ((Node)clause))
  565.     return (clause);
  566.     else if (or_clause (clause)) 
  567.     return (make_orclause (replace_subclause_joinvar_refs 
  568.                  (get_orclauseargs (clause),
  569.                   outer_tlist,
  570.                   inner_tlist)));
  571.     else if (IsA(clause,ArrayRef)) {
  572.     LispValue temp;
  573.     temp = replace_clause_joinvar_refs(get_refindexpr((ArrayRef)clause),
  574.                           outer_tlist,
  575.                           inner_tlist);
  576.     set_refindexpr((ArrayRef)clause,temp);
  577.     temp = replace_clause_joinvar_refs(get_refexpr((ArrayRef)clause),
  578.                           outer_tlist,
  579.                           inner_tlist);
  580.     set_refexpr((ArrayRef)clause,temp);
  581.     return(clause);
  582.       }
  583.     else if (is_funcclause (clause)) {
  584.     return (make_funcclause (get_function (clause),
  585.                        replace_subclause_joinvar_refs 
  586.                         (get_funcargs (clause),
  587.                         outer_tlist,
  588.                         inner_tlist)));
  589.        }
  590.     else if (not_clause (clause)) 
  591.      return (make_notclause (replace_clause_joinvar_refs 
  592.                       (get_notclausearg (clause),
  593.                     outer_tlist,
  594.                        inner_tlist)));
  595.     else if (is_clause (clause)) 
  596.      return (make_opclause(replace_opid((Oper)get_op(clause)),
  597.                      (Var)replace_clause_joinvar_refs 
  598.                      ((LispValue)get_leftop (clause),
  599.                        outer_tlist,
  600.                       inner_tlist),
  601.                      (Var)replace_clause_joinvar_refs 
  602.                      ((LispValue)get_rightop (clause),
  603.                       outer_tlist,
  604.                       inner_tlist)));
  605. }  /* function end  */
  606.  
  607. /*  .. join-references, replace-clause-joinvar-refs     */
  608.  
  609. LispValue
  610. replace_subclause_joinvar_refs (clauses,outer_tlist,inner_tlist)
  611.      LispValue clauses,outer_tlist,inner_tlist ;
  612. {
  613.      LispValue t_list = LispNil;
  614.      LispValue temp = LispNil;
  615.      LispValue clause = LispNil;
  616.  
  617.      foreach (clause,clauses) {
  618.       temp = replace_clause_joinvar_refs (CAR(clause),
  619.                           outer_tlist,
  620.                           inner_tlist);
  621.       t_list = nappend1(t_list,temp);
  622.      }
  623.      return(t_list);
  624.  
  625. } /* function end  */
  626.  
  627. /*  .. replace-clause-joinvar-refs      */
  628.  
  629. Var
  630. replace_joinvar_refs (var,outer_tlist,inner_tlist)
  631.      Var var;
  632.      List outer_tlist,inner_tlist ;
  633. {
  634.     Resdom outer_resdom =(Resdom)NULL;
  635.  
  636.     outer_resdom= tlist_member(var,outer_tlist);
  637.  
  638.     if ( !null(outer_resdom) && IsA (outer_resdom,Resdom) ) {
  639.      return (MakeVar (OUTER,
  640.               get_resno (outer_resdom),
  641.               get_vartype (var),
  642.               get_varid (var),
  643.               0));
  644.      } 
  645.     else {
  646.     Resdom inner_resdom;
  647.     inner_resdom = tlist_member(var,inner_tlist);
  648.     if ( !null(inner_resdom) && IsA (inner_resdom,Resdom) ) {
  649.         return (MakeVar (INNER,
  650.                  get_resno (inner_resdom),
  651.                  get_vartype (var),
  652.                  get_varid (var),
  653.                  0));
  654.      } 
  655.     } 
  656.     return (Var) NULL;
  657.  
  658. }  /* function end  */
  659.  
  660. /*    
  661.  *        tlist-temp-references
  662.  *    
  663.  *        Creates a new target list for a node that scans a temp relation,
  664.  *        setting the varnos to the id of the temp relation and setting varids
  665.  *        if necessary (varids are only needed if this is a targetlist internal
  666.  *        to the tree, in which case the targetlist entry always contains a var
  667.  *        node, so we can just copy it from the temp).
  668.  *    
  669.  *        'tempid' is the id of the temp relation
  670.  *        'tlist' is the target list to be modified
  671.  *    
  672.  *        Returns new target list
  673.  *    
  674.  */
  675.  
  676. /*  .. set-tempscan-tlist-references, sort-level-result     */
  677.  
  678. List
  679. tlist_temp_references (tempid,tlist)
  680.      ObjectId tempid;
  681.      List tlist ;
  682. {
  683.      LispValue t_list = LispNil;
  684.      TLE temp = (TLE)NULL;
  685.      LispValue xtl = LispNil;
  686.      LispValue var1 = LispNil;
  687.      LispValue entry;
  688.      
  689.      foreach (entry,tlist) {
  690.      xtl = CAR(entry);
  691.      if ( IsA(get_expr (xtl),Var))
  692.        var1 = get_varid (get_expr (xtl));
  693.       else
  694.         var1 = LispNil;
  695.      
  696.      temp = (TLE)MakeTLE (tl_resdom (xtl),
  697.                   MakeVar(tempid,
  698.                       get_resno((Resdom)tl_resdom (xtl)),
  699.                   get_restype ((Resdom)tl_resdom (xtl)),
  700.                       var1,
  701.                       0));
  702.      
  703.      t_list = nappend1(t_list,temp);
  704.      }
  705.      return(t_list);
  706.  }  /* function end  */
  707.  
  708. /*---------------------------------------------------------
  709.  *
  710.  * set_result_tlist_references
  711.  *
  712.  * Change the target list of a Result node, so that it correctly
  713.  * addresses the tuples returned by its left tree subplan.
  714.  *
  715.  * NOTE:
  716.  *  1) we ignore the right tree! (in the current implementation
  717.  *     it is always nil
  718.  *  2) this routine will probably *NOT* work with nested dot
  719.  *     fields....
  720.  */
  721. void
  722. set_result_tlist_references(resultNode)
  723. Result resultNode;
  724. {
  725.     Plan subplan;
  726.     List resultTargetList;
  727.     List subplanTargetList;
  728.     LispValue t;
  729.     TLE entry;
  730.     Expr expr;
  731.  
  732.     resultTargetList= get_qptargetlist((Plan)resultNode);
  733.  
  734.     /*
  735.      * NOTE: we only consider the left tree subplan.
  736.      * This is usually a seq scan.
  737.      */
  738.     subplan = (Plan)get_lefttree((Plan)resultNode);
  739.     if (subplan != NULL) {
  740.     subplanTargetList = get_qptargetlist(subplan);
  741.     } else {
  742.     subplanTargetList = LispNil;
  743.     }
  744.  
  745.     /*
  746.      * now for traverse all the entris of the target list.
  747.      * These should be of the form (Resdom_Node Expression).
  748.      * For every expression clause, call "replace_result_clause()"
  749.      * to appropriatelly change all the Var nodes.
  750.      */
  751.     foreach (t, resultTargetList) {
  752.     entry = (TLE) CAR(t);
  753.     expr = (Expr) get_expr(entry);
  754.     replace_result_clause((LispValue)expr, subplanTargetList);
  755.     }
  756.  
  757. }
  758.  
  759. /*---------------------------------------------------------
  760.  *
  761.  * replace_result_clause
  762.  *
  763.  * This routine is called from set_result_tlist_references().
  764.  * and modifies the expressions of the target list of a Result
  765.  * node so that all Var nodes reference the target list of its subplan.
  766.  * 
  767.  */
  768.  
  769. void
  770. replace_result_clause(clause, subplanTargetList)
  771. LispValue clause;
  772. List subplanTargetList;        /* target list of the subplan */
  773. {
  774.     
  775.     Expr subExpr;
  776.     LispValue t;
  777.     List subClause;
  778.     LispValue subplanVar;
  779.  
  780.     if (IsA(clause,Var)) {
  781.     /*
  782.      * Ha! A Var node!
  783.      */
  784.     subplanVar = match_varid((Var)clause, subplanTargetList);
  785.     /*
  786.      * Change the varno & varattno fields of the
  787.      * var node.
  788.      *
  789.      */
  790.     set_varno((Var)clause,(Index) OUTER);
  791.     set_varattno((Var)clause, get_resno((Resdom)tl_resdom(subplanVar)));
  792.     } else if (is_funcclause(clause)) {
  793.     /*
  794.      * This is a function. Recursively call this routine
  795.      * for its arguments...
  796.      */
  797.     subClause = get_funcargs(clause);
  798.     foreach (t, subClause) {
  799.         replace_result_clause(CAR(t),subplanTargetList);
  800.        }
  801.     } else if (IsA(clause,ArrayRef)) {
  802.     /*
  803.      * This is an arrayref. Recursively call this routine
  804.      * for its expression and its index expression...
  805.      */
  806.     replace_result_clause(get_refindexpr((ArrayRef)clause),
  807.                   subplanTargetList);
  808.     replace_result_clause(get_refexpr((ArrayRef)clause),
  809.                   subplanTargetList);
  810.     } else if (is_clause(clause)) {
  811.     /*
  812.      * This is an operator. Recursively call this routine
  813.      * for both its left and right operands
  814.      */
  815.     subClause = (List)get_leftop(clause);
  816.     replace_result_clause(subClause,subplanTargetList);
  817.     subClause = (List)get_rightop(clause);
  818.     replace_result_clause(subClause,subplanTargetList);
  819.     } else if (IsA(clause,Param) || IsA(clause,Const)) {
  820.     /* do nothing! */
  821.     } else {
  822.     /*
  823.      * Ooops! we can not handle that!
  824.      */
  825.     elog(WARN,"replace_result_clause: Can not handle this tlist!\n");
  826.     }
  827. }
  828.  
  829. bool
  830. OperandIsInner(opnd, inner_relid)
  831.     LispValue opnd;
  832.     int inner_relid;
  833. {
  834.  
  835.     /*
  836.      * Can be the inner scan if its a varnode or a function and the
  837.      * inner_relid is equal to the varnode's var number or in the 
  838.      * case of a function the first argument's var number (all args
  839.      * in a functional index are from the same relation).
  840.      */
  841.     if ( IsA (opnd,Var) && 
  842.      (inner_relid == get_varno((Var)opnd)) )
  843.     {
  844.     return true;
  845.     }
  846.     if ( consp(opnd) && IsA(CAR(opnd),Func) )
  847.     {
  848.     LispValue firstArg = CAR(get_funcargs(opnd));
  849.  
  850.     if ( IsA (firstArg,Var) &&
  851.          (inner_relid == get_varno((Var)firstArg)) )
  852.     {
  853.         return true;
  854.     }
  855.     }
  856.     return false;
  857. }
  858.